package com.yami.shop.rights.common.strategy;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yami.shop.bean.event.AddRightsEvent;
import com.yami.shop.bean.event.TransferRightsEvent;
import com.yami.shop.bean.event.UpdateRightsEvent;
import com.yami.shop.bean.model.ProdNft;
import com.yami.shop.bean.param.RightsParam;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.personnft.common.service.PersonNftService;
import com.yami.shop.rights.common.dao.PersonRightsMapper;
import com.yami.shop.rights.common.dto.PersonRightsDto;
import com.yami.shop.rights.common.model.PersonRights;
import com.yami.shop.rights.common.model.ProdRights;
import com.yami.shop.rights.common.model.RightsRecord;
import com.yami.shop.rights.common.model.RightsTransferRecord;
import com.yami.shop.rights.common.service.PersonRightsService;
import com.yami.shop.rights.common.service.ProdRightsService;
import com.yami.shop.rights.common.service.RightsRecordService;
import com.yami.shop.rights.common.service.RightsTransferRecordService;
import com.yami.shop.rights.common.vo.ProdRightDetailVo;
import com.yami.shop.security.common.util.AuthUserContext;
import com.yami.shop.service.ProdNftService;
import com.yami.shop.service.ProductService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
@Log4j2
public class PersonRightsFactory {

    private final Map<String, PersonRightsStrategy> map = new ConcurrentHashMap<>();

    @Autowired
    private ProdNftService prodNftService;
    @Autowired
    private ProdRightsService prodRightsService;
    @Autowired
    private PersonRightsService personRightsService;
    @Autowired
    private RightsRecordService rightsRecordService;
    @Autowired
    private ProductService productService;
    @Autowired
    private PersonNftService personNftService;
    @Autowired
    private PersonRightsMapper personRightsMapper;
    @Autowired
    private RightsTransferRecordService rightsTransferRecordService;

    @Autowired
    public PersonRightsFactory(List<PersonRightsStrategy> strategies) {
        strategies.forEach(personRightsStrategy -> {
            map.put(personRightsStrategy.rightsType(), personRightsStrategy);
        });
    }

    @Transactional
    public void saveOrUpdate(ProdRights dto) {
        prodRightsService.saveOrUpdate(dto);
        // 判断该 权益是否被商品绑定
        if (ObjectUtil.isNotEmpty(dto.getId())) {
            QueryWrapper<ProdNft> queryWrapper = new QueryWrapper<>();
            queryWrapper.like("rights_id", dto.getId());
            List<ProdNft> list = prodNftService.list(queryWrapper);
            if (ObjectUtil.isNotEmpty(list)) {
                log.info("该权益已关联商品无法修改绑定信息");
                return;
            }
        }
        PersonRightsStrategy personRightsStrategy = map.get(dto.getType());
        personRightsStrategy.savePersonRightsData(dto);
    }

    public Long getSurplusTimes(long id, String type) {
        PersonRightsStrategy personRightsStrategy = map.get(type);
        return personRightsStrategy.getSurplusTimes(id);
    }

    @Transactional
    public void addPersonRights(AddRightsEvent event) {

        // 获取权益信息 通过商品ID 或 权益ID
        QueryWrapper<ProdRights> prodRightsQueryWrapper = new QueryWrapper<>();
        if(ObjectUtil.isNotEmpty(event.getRights())){
            prodRightsQueryWrapper.eq("id", event.getRights());
            prodRightsQueryWrapper.eq("status", "1");
        }else{
            ProdNft dataByProdId = prodNftService.getDataByProdId(event.getProdId());
            log.info("增加权益信息=========商品ID{}======================权益ID={}", event.getProdId(), dataByProdId.getRightsId());
            if (ObjectUtil.isEmpty(dataByProdId.getRightsId())) {
                return;
            }
            prodRightsQueryWrapper.in("id", Arrays.asList(dataByProdId.getRightsId().split(",")));
            prodRightsQueryWrapper.eq("status", "1");

        }
        List<ProdRights> prodRightsList = prodRightsService.list(prodRightsQueryWrapper);
        // 权益新增
        for (ProdRights prodRights : prodRightsList) {
            PersonRights personRights = new PersonRights();
            personRights.setRightsId(prodRights.getId());
            personRights.setTokenId(event.getTokenId());
            personRights.setUserId(event.getUserId());
            personRights.setStatus(0);
            // 新增权益信息
            personRights.setTimes(prodRights.getDrawCount());
            // 新增数据
            personRightsService.save(personRights);

            PersonRightsStrategy personRightsStrategy = map.get(prodRights.getType());
            personRightsStrategy.addPersonRights(prodRights, event, personRights.getId());
        }
    }

    @Transactional
    public void verificationRights(JSONObject qrCodeData) {

        PersonRightsStrategy personRightsStrategy = map.get(qrCodeData.getString("type"));
        List<PersonRightsDto> personRightsDtos = personRightsStrategy.verificationRights(qrCodeData);
        if (ObjectUtil.isEmpty(personRightsDtos)) {
            return;
        }
        // 新增权益使用记录
        List<RightsRecord> rightsRecords = new ArrayList<>();
        personRightsDtos.forEach(s -> {
            RightsRecord rightsRecord = new RightsRecord();
            rightsRecord.setPersonRightsId(s.getId());
            rightsRecord.setRightsId(s.getRightsId());
            rightsRecord.setRemark(s.getRemark());
            rightsRecord.setStatus( qrCodeData.getLongValue("addressId")!= 0L ? "1" :s.getStatus() ); //如果有地址表示冻结待确认收货后再改为使用
            // 被核销人
            rightsRecord.setUserId(s.getUserId());
            // 核销人
            rightsRecord.setHolderUserId(s.getHolderUserId());
            rightsRecord.setTimes(s.getTimes());
            rightsRecord.setRecordType(qrCodeData.getString("type"));
            rightsRecords.add(rightsRecord);
            // 修改权益使用状态
            if(s.getStatusUpdate() != 0){
                LambdaUpdateWrapper<PersonRights> personRightsLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                personRightsLambdaUpdateWrapper.eq(PersonRights::getId,s.getId());
                personRightsLambdaUpdateWrapper.set(PersonRights::getStatus,qrCodeData.getLongValue("addressId")!= 0L ? "4" :s.getStatusUpdate());//如果有地址表示冻结待确认收货后再改为使用
                personRightsService.update(personRightsLambdaUpdateWrapper);
            }
        });
        rightsRecordService.saveBatch(rightsRecords);

    }


    public void updatePersonRights(UpdateRightsEvent updateRightsEvent) {
        // 通过token 查询权益信息
        List<PersonRightsDto> personRightsDtos = personRightsService.getPersonRightsByTokenId(updateRightsEvent.getTokenId());
        log.info("转移权益的数量{}",personRightsDtos.size());
        // 当前版本 只有 优先购资格 再发生 token转移的情况下会 修改信息
        for (PersonRightsDto personRightsDto : personRightsDtos) {
            if ("9".equals(personRightsDto.getType()) || "13".equals(personRightsDto.getType()) ) {
                PersonRightsStrategy personRightsStrategy = map.get(personRightsDto.getType());
                personRightsStrategy.updatePersonRights(personRightsDto.getRightsId(),personRightsDto.getId() + "", updateRightsEvent.getUserId(), updateRightsEvent.getToUserId());
            }
            // token发生转移权益持有人 修改 --- 当前版本不考虑权益持有人
            LambdaUpdateWrapper<PersonRights> personRightsLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            personRightsLambdaUpdateWrapper.eq(PersonRights::getId,personRightsDto.getId());
            personRightsLambdaUpdateWrapper.set(PersonRights::getUserId,updateRightsEvent.getToUserId());
            personRightsService.update(personRightsLambdaUpdateWrapper);

        }
    }


    public void cancelOrder(Long orderNumber, String type) {
        PersonRightsStrategy personRightsStrategy = map.get(type);
        personRightsStrategy.cancelOrder(orderNumber);
    }

    public List<ProdRightDetailVo> getRightsDetails(String tokenId) {
        List<ProdRightDetailVo> personRightsDtos = new ArrayList<>();
        // 获取token下权益信息
        List<PersonRightsDto> personRightsByTokenId = personRightsService.getPersonRightsByTokenId(tokenId);
        // 处理权益信息数据
        Map<Long, List<PersonRightsDto>> maps = personRightsByTokenId.stream().collect(Collectors.groupingBy(PersonRightsDto::getRightsId));
        for (Map.Entry<Long, List<PersonRightsDto>> entry : maps.entrySet()) {
            ProdRightDetailVo prodRightDetailVo = new ProdRightDetailVo();
            if (entry.getValue().size() == 1 && entry.getValue().get(0).getPreemptionType() == 2) {
                prodRightDetailVo.setRightsTimes(0L);
                prodRightDetailVo.setRightsName(entry.getValue().get(0).getRightsName() + "(通用)");
            } else {
                prodRightDetailVo.setRightsTimes((long) entry.getValue().size());
                prodRightDetailVo.setRightsName(entry.getValue().get(0).getRightsName());
            }
            prodRightDetailVo.setType(entry.getValue().get(0).getType());
            prodRightDetailVo.setRightsId(entry.getKey());
            // 权益状态 -- 状态 升序 0 未使用 1 使用 3 过期   取第一条
            List<PersonRightsDto> collect = entry.getValue().stream().sorted().collect(Collectors.toList());
            prodRightDetailVo.setStatus(collect.get(0).getStatus());
            // 不差次数 -- 先注释掉
//            Long surplusTimesSum = 0L;
            for (PersonRightsDto personRightsDto : entry.getValue()) {
                prodRightDetailVo.setId(personRightsDto.getId());
//                PersonRightsStrategy personRightsStrategy = map.get(prodRightDetailVo.getType());
//                surplusTimesSum += personRightsStrategy.getSurplusTimes(personRightsDto.getId());
            }
//            prodRightDetailVo.setRightsSurplusTimes(surplusTimesSum);
            personRightsDtos.add(prodRightDetailVo);
        }
        return personRightsDtos;
    }

    public IPage<ProdRightDetailVo> getRightsLists(PageParam<ProdRightDetailVo> page) {
        String userId = AuthUserContext.get().getUserId();
        // 获取带有权益的 商品Id
        List<Long> prods = productService.prodIdsByRightsList();
        // 获取对应的所有权益信息
        IPage<PersonRightsDto> personRightsByTokenId = personRightsMapper.getPersonRightsByProdIds(page,prods,userId,null);


        IPage<ProdRightDetailVo> personRightsDtos =  new Page<>();
        List<ProdRightDetailVo> retRecords = new ArrayList<>();
        // 处理权益信息数据
        Map<Long, List<PersonRightsDto>> maps = personRightsByTokenId.getRecords().stream().collect(Collectors.groupingBy(PersonRightsDto::getRightsId));
        for (Map.Entry<Long, List<PersonRightsDto>> entry : maps.entrySet()) {
            ProdRightDetailVo prodRightDetailVo = new ProdRightDetailVo();
            if (entry.getValue().size() == 1 && entry.getValue().get(0).getPreemptionType() == 2) {
                prodRightDetailVo.setRightsTimes(0L);
                prodRightDetailVo.setRightsName(entry.getValue().get(0).getRightsName() + "(通用)");
            } else {
                prodRightDetailVo.setRightsTimes((long) entry.getValue().size());
                prodRightDetailVo.setRightsName(entry.getValue().get(0).getRightsName());
            }
            prodRightDetailVo.setType(entry.getValue().get(0).getType());
            prodRightDetailVo.setRightsId(entry.getKey());
            // 权益状态 -- 状态 升序 0 未使用 1 使用 3 过期   取第一条
            List<PersonRightsDto> collect = entry.getValue().stream().sorted(Comparator.comparing(PersonRightsDto::getStatus)).collect(Collectors.toList());
            prodRightDetailVo.setStatus(collect.get(0).getStatus());
            // 不查询次数 -- 先注释掉
//            Long surplusTimesSum = 0L;
            for (PersonRightsDto personRightsDto : entry.getValue()) {
                prodRightDetailVo.setId(personRightsDto.getId());
//                PersonRightsStrategy personRightsStrategy = map.get(prodRightDetailVo.getType());
//                surplusTimesSum += personRightsStrategy.getSurplusTimes(personRightsDto.getId());
            }
//            prodRightDetailVo.setRightsSurplusTimes(surplusTimesSum);
            retRecords.add(prodRightDetailVo);
        }
        personRightsDtos.setRecords(retRecords);
        personRightsDtos.setTotal(personRightsByTokenId.getTotal());
        personRightsDtos.setPages(personRightsByTokenId.getPages());
        return personRightsDtos;
    }
    public IPage<ProdRightDetailVo> getNoUseRightsLists(PageParam<ProdRightDetailVo> page , Integer status,String userId) {
        // 获取带有权益的 商品Id
//        List<Long> prods = productService.prodIdsByRightsList();
        List<Long> prods = new ArrayList<>();
        // 获取对应的所有权益信息
        IPage<PersonRightsDto> personRightsByTokenId = personRightsMapper.getPersonRightsByProdIds(page,prods,userId,status);
        IPage<ProdRightDetailVo> personRightsDtos = new Page<>();

        List<ProdRightDetailVo> retRecords = new ArrayList<>();

        List<PersonRightsDto> records = personRightsByTokenId.getRecords();
        records.forEach(s->{
            ProdRightDetailVo prodRightDetailVo = new ProdRightDetailVo();
            if("9".equals(s.getType()) && s.getPreemptionType()!=null && s.getPreemptionType() == 2){
                prodRightDetailVo.setRightsTimes(1L);
                prodRightDetailVo.setRightsName(s.getRightsName() + "(通用)");
            }else{
                prodRightDetailVo.setRightsTimes(1L);
                prodRightDetailVo.setRightsName(s.getRightsName());
            }
            prodRightDetailVo.setType(s.getType());
            prodRightDetailVo.setRightsId(s.getRightsId());
            // 权益状态 -- 状态 升序 0 未使用 1 使用 3 过期
            prodRightDetailVo.setStatus(s.getStatus());
            prodRightDetailVo.setId(s.getId());
            prodRightDetailVo.setExchangeEndTime(s.getExchangeEndTime());
            retRecords.add(prodRightDetailVo);
        });
        personRightsDtos.setSize(personRightsByTokenId.getSize());
        personRightsDtos.setCurrent(personRightsByTokenId.getCurrent());
        personRightsDtos.setRecords(retRecords);
        personRightsDtos.setTotal(personRightsByTokenId.getTotal());
        personRightsDtos.setPages(personRightsByTokenId.getPages());
        return personRightsDtos;
    }

    public IPage<ProdRights>  getPersonRightsByProId(PageParam<ProdRights> page, RightsParam rightsParam) {
        IPage<ProdRights> personRightsByProId = personRightsMapper.getPersonRightsByProId(page, rightsParam);
        List<ProdRights> records = personRightsByProId.getRecords();
        records.forEach(s->{
            if("9".equals(s.getType()) && s.getPreemptionType()!=null && s.getPreemptionType() == 2){
                s.setRightsName(s.getRightsName() + "(通用)");
            }
        });
        return personRightsByProId;
    }

    public void updateRightsEffective(List<ProdRights> list) {
        Map<String, List<ProdRights>> collect = list.stream().collect(Collectors.groupingBy(ProdRights::getType));
        for(Map.Entry<String, List<ProdRights>> entry : collect.entrySet()){
            List<Long> rightsId = entry.getValue().stream().map(ProdRights::getId).collect(Collectors.toList());
            // 修改权益token关联表为过期
            LambdaUpdateWrapper<PersonRights> personRightsLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            personRightsLambdaUpdateWrapper.in(PersonRights::getRightsId, rightsId);
            personRightsLambdaUpdateWrapper.eq(PersonRights::getStatus, 0);
            personRightsLambdaUpdateWrapper.set(PersonRights::getStatus, 3);
            personRightsService.update(personRightsLambdaUpdateWrapper);
            // 获取权益token关联表ID
            QueryWrapper<PersonRights> personRightsQueryWrapper = new QueryWrapper<>();
            personRightsQueryWrapper.in("rights_id",rightsId);
            List<PersonRights> personRights = personRightsMapper.selectList(personRightsQueryWrapper);
            List<Long> personRightsId = personRights.stream().map(PersonRights::getId).collect(Collectors.toList());
            //
            PersonRightsStrategy personRightsStrategy = map.get(entry.getKey());
            personRightsStrategy.updateRightsEffective(personRightsId);
        }

    }

    @Transactional
    public void rightsTransfer(TransferRightsEvent event) {
        // 调用权益转移逻辑
        PersonRightsStrategy personRightsStrategy = map.get(event.getPersonRightsType());
        personRightsStrategy.rightsTransfer(event);
        // 修改转移状态
        RightsTransferRecord rightsTransferRecord = new RightsTransferRecord();
        rightsTransferRecord.setId(event.getRightsTransferRecordId());
        rightsTransferRecord.setStatus(2);
        rightsTransferRecord.setFinalData(event.getFinalData());
        rightsTransferRecordService.updateById(rightsTransferRecord);
        // 修改权益用有人
        PersonRights personRights = new PersonRights();
        personRights.setId(event.getPersonRightsId());
        personRights.setUserId(event.getReceiveUser());
        personRightsService.updateById(personRights);
    }

}
